/**
 *
 */
package com.angel.io.type.rows.impl;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Iterator;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;

import com.angel.common.helpers.StringHelper;
import com.angel.io.exceptions.InvalidRowDataException;
import com.angel.io.exceptions.InvalidRowValueAccessException;
import com.angel.io.type.rows.ExportRowFile;
import com.angel.io.type.rows.ImportRowFile;

/**
 * @author William
 *
 */
public class ExcelRowFile implements ImportRowFile, ExportRowFile{

	private HSSFRow row;

	public ExcelRowFile(HSSFRow row){
		super();
		this.row = row;
	}

	public Float getFloatValue(int position) {
		String value = this.getStringValueCell(this.getRow(), position);
		return Float.valueOf(StringHelper.isEmpty(value) ? "0": value);
	}

	private String getStringValueCell(HSSFRow row, int position){
		String value = "";
		HSSFCell cell = row.getCell(position);
		if(cell != null){
			if(cell.getCellType() == 0){ //Numeric
				/** TODO With a date cell value, cell type enter here. So i couldn't get a Date here, because it
				 * is a string. So, if you want write a date value in a cell, you must write as a string.
				 * For example: "'09/10/2008'" (with simple quotes).
				 */
				DecimalFormat decimalFormat = new DecimalFormat("00000.#");
				value = decimalFormat.format(cell.getNumericCellValue());
			} else if(cell.getCellType() == 1){//String
				value = this.getRow().getCell(position).getRichStringCellValue().getString();
			} else if(cell.getCellType() == 2){//Formula
				value = this.getRow().getCell(position).getRichStringCellValue().getString();
			} else if(cell.getCellType() == 3){//Blank
				value = StringHelper.EMPTY_STRING;
			} else if(cell.getCellType() == 4){//Boolean
				value = String.valueOf(this.getRow().getCell(position).getBooleanCellValue());
			} else if(cell.getCellType() == 5){//Error
				value = String.valueOf(this.getRow().getCell(position).getErrorCellValue());
			} else {
				value = StringHelper.EMPTY_STRING;
			}
		}
		return value;
	}

	@SuppressWarnings("unchecked")
	public Float[] getFloatValues() {
		int quantity = this.quantityColumns();
		Float[] floatsValues = new Float[quantity];
		Iterator<HSSFCell> cells = this.row.cellIterator();
		int i = 0;
		while(cells.hasNext()){
			HSSFCell cell = cells.next();
			floatsValues[i] = Float.valueOf(this.getStringValueCell(this.getRow(), cell.getColumnIndex()));
		}
		return floatsValues;
	}

	public Integer getIntegerValue(int position) {
		String value = this.getStringValueCell(this.getRow(), position);
		return Integer.valueOf(value);
	}

	@SuppressWarnings("unchecked" )
	public Integer[] getIntegerValues() {
		int quantity = this.quantityColumns();
		Integer[] integerValues = new Integer[quantity];
		Iterator<HSSFCell> cells = this.row.cellIterator();
		int i = 0;
		while(cells.hasNext()){
			HSSFCell cell = cells.next();
			integerValues[i] = Integer.valueOf(this.getStringValueCell(this.getRow(), cell.getColumnIndex()));
		}
		return integerValues;
	}

	public String getStringValue(int position) {
		return this.getStringValueCell(this.getRow(), position);
	}

	@SuppressWarnings("unchecked")
	public String[] getStringValues() {
		int quantity = this.quantityColumns();
		String[] stringValues = new String[quantity];
		Iterator<HSSFCell> cells = this.row.cellIterator();
		int i = 0;
		while(cells.hasNext()){
			HSSFCell cell = cells.next();
			stringValues[i] = this.getStringValueCell(this.getRow(), cell.getColumnIndex());
			i++;
		}
		return stringValues;
	}

	public Object getValue(int position) {
		String value = this.getStringValueCell(this.getRow(), position);
		return value;
	}

	@SuppressWarnings("unchecked")
	public Object[] getValues() {
		int quantity = this.quantityColumns();
		Object[] objectValues = new Object[quantity];
		Iterator<HSSFCell> cells = this.row.cellIterator();
		int i = 0;
		while(cells.hasNext()){
			HSSFCell cell = cells.next();
			objectValues[i] = this.getStringValueCell(this.getRow(), cell.getColumnIndex());
			i++;
		}
		return objectValues;
	}

	/**
	 * @return the row
	 */
	public HSSFRow getRow() {
		return row;
	}

	public Date getDateValue(DateFormat dateFormat, int position) {
		String value = this.getStringValueCell(this.getRow(), position);
		try {
			if(value != null){
				return dateFormat.parse(value);
			}
		} catch (ParseException e) {
			throw new InvalidRowDataException("Invalid date format dateFormat: [" + dateFormat.getNumberFormat()+"]" + " for date: [" + value + "].", e);
		}
		return new Date();
	}

	public int quantityColumns() {
		return this.row != null ? this.row.getLastCellNum() : 0;
	}


	public String toString(){
		String allValues = "";
		for(String value : this.getStringValues()){
			allValues = allValues.concat(value + " - ");
		}
		return  allValues;
	}

	public void addDateValue(Date value, DateFormat dateFormat, int position) {
		this.checkValue(value, position);
		HSSFCell cell = this.row.createCell(position);
		cell.setCellValue(new HSSFRichTextString(dateFormat.format(value)));
	}

	public void addFloatValue(Float value, int position) {
		this.checkValue(value, position);
		HSSFCell cell = this.row.createCell(position);
		cell.setCellValue(new HSSFRichTextString(value.toString()));
	}

	public void addIntegerValue(Integer value, int position) {
		this.checkValue(value, position);
		HSSFCell cell = this.row.createCell(position);
		cell.setCellValue(new HSSFRichTextString(value.toString()));
	}

	public void addStringValue(String value, int position) {
		this.checkValue(value, position);
		HSSFCell cell = this.row.createCell(position);
		cell.setCellValue(new HSSFRichTextString(value.toString()));
	}
	
	public void checkValue(Object value, int position) {
		if(value == null){
			throw new InvalidRowValueAccessException("Error checking value. Value cannot be null at position [" + position + "] begining in zero.");
		}
	}

	public void addValue(Object value, int position) {
		this.checkValue(value, position);
		HSSFCell cell = this.row.createCell(position);
		cell.setCellValue(new HSSFRichTextString(value.toString()));
	}


	public String export() {
		return this.toString();
	}

	public Double getDoubleValue(int position) {
		String value = this.getStringValueCell(this.getRow(), position);
		return Double.valueOf(value);
	}

	@SuppressWarnings("unchecked")
	public Double[] getDoubleValues() {
		int quantity = this.quantityColumns();
		Double[] doubleValues = new Double[quantity];
		Iterator<HSSFCell> cells = this.row.cellIterator();
		int i = 0;
		while(cells.hasNext()){
			HSSFCell cell = cells.next();
			doubleValues[i] = Double.valueOf(this.getStringValueCell(this.getRow(), cell.getColumnIndex()));
			i++;
		}
		return doubleValues;
	}

	public void addDoubleValue(Double value, int position) {
		this.checkValue(value, position);
		HSSFCell cell = this.row.createCell(position);
		cell.setCellValue(new HSSFRichTextString(value.toString()));
	}

	public boolean isEmpty() {
		if(this.getRow() != null){
			String[] values = this.getStringValues();
			for(String value: values){
				if(!StringHelper.isEmpty(value)){
					return false;
				}
			}

		}
		return true;
	}
}
